package com.apache.common.plugins;

import com.apache.api.vo.ParamsVo;
import com.apache.api.vo.ResultEntity;
import com.apache.cache.util.Validator;
import com.apache.exception.BusinessException;
import com.apache.ius.plugin.CustomMethodPlugin;
import com.apache.ius.plugin.IusPluginUtil;
import com.apache.tools.DataMap;
import com.apache.tools.NumberUtils;
import com.apache.tools.StrUtil;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * 是否唯一值校验
 * @Author cbqiu
 * @Date 2019-4-16  2020/12/18
 */
public class UniqueCheckPluginImpl implements CustomMethodPlugin {
	private Logger log = LoggerFactory.getLogger(getClass());

	@Override
	public Object beforeInvoke(Map<String, Object> param) {
		log.info("start->> 执行插件事前方法....");


		String modelType = String.valueOf(param.get("modelTypes"));
		String checkColumn = String.valueOf(param.get("checkColumn"));
		/**
		 * 该字段配置约定格式分如下几种情况：
		 * 1、(字符串)对象.属性-->【只是验证某一个字段是否重复】
		 * 2、(字符串)对象.属性,对象.属性-->【可验证多个字段(逗号分隔)是否同时(并且)满足重复】
		 * 3、(JSON数组)如：[{"key":"对象.属性","msg":"编号"},{"key":"对象.属性","msg":"名称"}]-->【可以自定义返回内容字段中文名称、同时支持修改判断字段重复性】
		 */
		log.info("checkColumn判重规则->"+checkColumn);
		if(!StrUtil.isNull(modelType)){
			if (isJSONArray(checkColumn)){//add 2020/12/18 支持JSON数组个性配置key和提示信息
				String[] objNameArray = modelType.split(",");
				for(int i=0;i<objNameArray.length;i++){
					String messageStr = "";
					JSONArray checkArray = JSONArray.fromObject(checkColumn);
					Map<String,Object> whereMap = new HashMap<String,Object>();
					String objName = objNameArray[i].split("_")[1];
					boolean objNameIsAdd = (objNameArray[i].indexOf("i_")>-1)?true:false;//判断是否新增
//					log.info("是否新增："+objNameIsAdd);
					for (int a=0;a<checkArray.size();a++){
						JSONObject obj = (JSONObject)checkArray.get(a);
						String key = obj.getString("key");
						String msg = obj.containsKey("msg")?(StrUtil.doNull(obj.getString("msg"),"")):"";
						if(!StrUtil.isNull(msg)){
							messageStr+=msg+",";
						}
						String [] colArray = key.split("\\.");
						String value =String.valueOf(param.get(key));
						if(Validator.isNull(value)){
							throw new BusinessException("["+key+"]的值不能为空，请输入后再次提交");
						}
						String flag = ".w_";//and
						String attrKey = objName+flag+colArray[1];
						whereMap.put(attrKey,value);
					}
					if(whereMap.size()>0){
						ResultEntity resultEntity = IusPluginUtil.getInstance().select(String.valueOf(param.get("datasource")),"list","s_"+objName,whereMap);
						if(null != resultEntity.getEntity()){
							List histList = (List)resultEntity.getEntity();
							log.info("checkCount->"+histList.size());
							if(histList.size() >0){
								if(!objNameIsAdd){
									boolean isMySelf = checkUpdateIsSelfObj(param, objName, histList);
									if(isMySelf){//修改时过滤掉自己改回自己原值重复的情况
										return null;
									}
								}
								if(messageStr.length()>0){
									messageStr=messageStr.substring(0,messageStr.length()-1);
								}
								log.error("查询到重复记录数："+String.valueOf(resultEntity.getEntity()));
								log.error(messageStr+"这些字段已存在重复数据，不能提交！");
								throw new BusinessException(messageStr+"的值已存在,不能重复提交！");
							}
						}
					}
				}
			}else{//之前历史配置（简单配置字段属性的）
				String[] objNameArray = modelType.split(",");
				for(int i=0;i<objNameArray.length;i++){
					//1、确保ius接口配置中要求校验的字段值不能为空
					Map<String,Object> whereMap = new HashMap<String,Object>();
					String objName = objNameArray[i].split("_")[1];
					if(Validator.isNotNull(checkColumn)){
						String [] colName ;
						String flag = ".w_";//and
						if(checkColumn.contains("||")){
							colName = checkColumn.split("\\|\\|");
							flag = ".wo_";//or
						}else{
							colName = checkColumn.split(",");
						}

					for (String col:colName) {
						//col:dictDataCate.cateEname
						String [] colArray = col.split("\\.");
						String confObjName = colArray[0];
						if(!confObjName.equals(objName)){
							continue;
						}

						String key = objName+flag+colArray[1];
						String value =String.valueOf(param.get(col));
						if(Validator.isNull(value)){
							throw new BusinessException("["+objName+"."+colArray[1]+"]的值不能为空，请输入后再次提交");
						}

						whereMap.put(key,value);
					}
					//获取sysEname，但不是每个表里都有这个字段
					if(Validator.isNotNull(String.valueOf(param.get(objName+".sysEname")))){
						whereMap.put(objName+".w_sysEname",String.valueOf(param.get(objName+".sysEname")));
					}

						if(whereMap.size()>0){
							ResultEntity resultEntity = IusPluginUtil.getInstance().select(String.valueOf(param.get("datasource")),"count","s_"+objName,whereMap);
							if(null != resultEntity.getEntity()){
								long histCount = NumberUtils.getInt(String.valueOf(resultEntity.getEntity()),0);
								log.info("checkCount->"+histCount);
								if(histCount >0){
									log.error("查询到重复记录数："+String.valueOf(resultEntity.getEntity()));
									log.error(checkColumn+",这些字段已存在重复数据，不能提交！");
									throw new BusinessException("已存在重复数据，不能提交！");
								}
							}
						}
					}
				}
			}
		}


		return null;
	}

	//判断修改时，是否修改的是自己，如果是自己这认为不重复，如果不是自己则认为是数据重复
	private boolean checkUpdateIsSelfObj(Map<String, Object> param, String objName, List histList) {
		String pkName = "";
		for(String key: param.keySet()){
			if(key.contains("w_")){
				pkName = key.split("w_")[1];
			}
		}
		DataMap firstObj = (DataMap)histList.get(0);
		String pk_this_val = String.valueOf(param.get(objName+".w_"+pkName));
		String pk_hist_val = String.valueOf(firstObj.get(pkName));
		if(!StrUtil.isNull(pk_this_val) && pk_this_val.equals(pk_hist_val)){
			return true;
		}
		return false;
	}

	@Override
	public Object doInvoke(Map<String, Object> param) {
		log.info("start->> 执行插件方法....");

		return null;
	}

	@Override
	public Object afterInvoke(Map<String, Object> param) {
		log.info("start->> 执行插件事后方法....");

		return null;
	}

	/**
	 * 规则校验统一入口
	 * @param paramsVo
	 */
	public void run(ParamsVo paramsVo) {
		beforeInvoke(paramsVo.getParams());
	}


	public static boolean isJSONObject(String str){
		if (StrUtil.isNull(str)){
			return false;
		}
		try {
			JSONObject parse = JSONObject.fromObject(str);
			return true;
		} catch (Exception e) {
			return false;
		}
	}
	public static boolean isJSONArray(String str){
		if (StrUtil.isNull(str)){
			return false;
		}
		try {
			JSONArray parse = JSONArray.fromObject(str);
			return true;
		} catch (Exception e) {
			return false;
		}
	}

	public static void main(String[] args) {
		System.out.println(isJSONArray("[{\"key\":\"flTools.toolsNo\",\"msg\":\"flTools.toolsName\"}]"));
	}
}

